package maps.forge;

import java.util.ArrayList;

import org.mapsforge.android.maps.ArrayItemizedOverlay;
import org.mapsforge.android.maps.GeoPoint;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.android.maps.MapViewMode;
import org.mapsforge.android.maps.OverlayItem;
import org.mapsforge.android.maps.RouteOverlay;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import de.fuberlin.osm2.data.DataBaseConnector;
import de.fuberlin.osm2.data.DataBaseConnectorImpl;
import de.fuberlin.osm2.data.dao.TrackData;

/**
 * OsMapView extends mapsforge - MapView. It shows OSM - informations using the
 * mapsforge - library. In order to load a map, an internet permission is
 * required.
 * 
 * @author user
 */
public class OsMapView extends MapView implements ServiceLocationListener {

	// RouteOverlay object to draw a line.
	RouteOverlay routeOverlay;
	Paint overlayPaint1; // RouteOverlay - color 1.
	Paint overlayPaint2; // RouteOverlay - color 2.

	// ItemizedOverlay object to draw POIs.
	ArrayItemizedOverlay poiOverlay;

	// A RouteOverlay uses an array of GeoPoints. We save them in an
	// ArrayList in order to add GeoPoints later without complications.
	ArrayList<GeoPoint> geoCoordinates = new ArrayList<GeoPoint>();

	// This is a second GeoPoint array.
	GeoPoint[] geoPoints;

	/**
	 * @param context
	 */
	public OsMapView(Context context) {
		super(context);
		initMap();
	}

	/**
	 * initMap() initialize our OsMapView.
	 */
	private void initMap() {

		// We tell OsMapView to handle click - commands
		// and to load map - informations online.
		this.setClickable(true);
		this.setBuiltInZoomControls(true);
		this.setMapViewMode(MapViewMode.MAPNIK_TILE_DOWNLOAD);

		// We define two Paint - objects.
		// Color 1:
		overlayPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
		overlayPaint1.setStyle(Paint.Style.STROKE);
		overlayPaint1.setColor(Color.rgb(0, 0, 255));
		overlayPaint1.setAlpha(160);
		overlayPaint1.setStrokeWidth(7);
		overlayPaint1.setStrokeCap(Paint.Cap.BUTT);
		overlayPaint1.setStrokeJoin(Paint.Join.ROUND);

		// Color 2:
		overlayPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
		overlayPaint2.setStyle(Paint.Style.STROKE);
		overlayPaint2.setColor(Color.rgb(200, 0, 255));
		overlayPaint2.setAlpha(160);
		overlayPaint2.setStrokeWidth(7);
		overlayPaint2.setStrokeCap(Paint.Cap.BUTT);
		overlayPaint2.setStrokeJoin(Paint.Join.ROUND);

		// Maybe we want to draw a finished track or we just compile
		// OsMapView for a second time. So we should check the database for
		// coordinates.
		double[] tmp;
		long trackId = 0; // TODO: get value of trackId
		DataBaseConnector dbc = new DataBaseConnectorImpl(this.getContext());
		TrackData trackData = dbc.getTrackData(trackId);
		tmp = trackData.getAllPoints();

		// Now add all coordinates to our GeoPoint - ArrayList.
		for (int i = 0; i < tmp.length; i += 2) {
			geoCoordinates.add(new GeoPoint(tmp[i + 1], tmp[i]));
		}

		// Maybe there is no point to draw (for example while adding a
		// new track). If there is no point we should wait for a first GPS -
		// coordinate.
		if (geoCoordinates.size() >= 1) {

			// O.K. There are points so we used to add them to our GeoPoint -
			// array.
			geoPoints = new GeoPoint[geoCoordinates.size()];
			for (int j = 0; j < geoCoordinates.size(); j++) {
				geoPoints[j] = geoCoordinates.get(j);
			}

			// Initialize the RouteOverlay with the specified colors.
			routeOverlay = new RouteOverlay(overlayPaint1, overlayPaint2);

			// Set the route data and add the RouteOverlay to our view.
			routeOverlay.setRouteData(geoPoints);
			this.getOverlays().add(routeOverlay);

			// In order to show the coordinates, we center them.
			// Otherwise the map shows an unimportant coordinate.
			this.getController().setCenter(geoPoints[geoPoints.length - 1]);
		}

		// Also we need a marker to draw POIs.
		// TODO: Load different POI - icons.
		Drawable POIMarker = getResources().getDrawable(
				de.fuberlin.osm2.R.drawable.osm_tag_toilets);

		// Now initialize poiOverlay.
		poiOverlay = new ArrayItemizedOverlay(POIMarker, this.getContext());

		// Add it to OsMapView.
		this.getOverlays().add(poiOverlay);
	}

	@Override
	public void onLocationUpdate(double longitude, double latitude) {

		// Add the new point to coordinate list.
		geoCoordinates.add(new GeoPoint(latitude, longitude));

		// We used to add them to our GeoPoint array.
		geoPoints = new GeoPoint[geoCoordinates.size()];
		for (int j = 0; j < geoCoordinates.size(); j++) {
			geoPoints[j] = geoCoordinates.get(j);
		}

		// If routeOverlay isn't initialized, initialize it.
		if (routeOverlay == null) {
			routeOverlay = new RouteOverlay(overlayPaint1, overlayPaint2);

			// Set the route data and add the RouteOverlay to our view.
			routeOverlay.setRouteData(geoPoints);
			this.getOverlays().add(routeOverlay);
			return;
		}

		// Set the route data.
		routeOverlay.setRouteData(geoPoints);

		// Now center the map.
		this.getController().setCenter(geoPoints[geoPoints.length - 1]);

	}

	@Override
	public void onPOI(double longitude, double latitude, String tag) {

		// First step: Create a new POI - marker.
		OverlayItem newPOI = new OverlayItem(new GeoPoint(latitude, longitude), "POI", tag);

		// Second step: Add it to POI - list.
		poiOverlay.addOverlay(newPOI);

	}

	@Override
	public void onStartWay() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStopWay() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStartArea() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStopArea() {
		// TODO Auto-generated method stub

	}

}
